package ${packageName}.controller;

import ${packageName}.config.TenantSecurityProperties;
import ${packageName}.security.JwtTokenProvider;
import ${packageName}.security.TenantAuthenticationService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;

/**
 * 多租户认证接口
 */
@RestController
@RequestMapping("/api/auth")
@Tag(name = "认证管理", description = "多租户JWT认证接口")
@Validated
@RequiredArgsConstructor
@Slf4j
public class AuthController {

    private final TenantAuthenticationService authenticationService;
    private final JwtTokenProvider tokenProvider;
    private final TenantSecurityProperties securityProperties;

    @PostMapping("/login")
    @Operation(summary = "登录并获取令牌", description = "使用租户ID、用户名和密码获取访问令牌与刷新令牌")
    public ResponseEntity<TokenResponse> login(@Valid @RequestBody LoginRequest request) {
        UserDetails userDetails = authenticationService.authenticate(
            request.getTenantId(), request.getUsername(), request.getPassword()
        );
        TokenResponse response = buildTokenResponse(request.getTenantId(), userDetails);
        log.info("租户 [{}] 用户 [{}] 登录成功", request.getTenantId(), request.getUsername());
        return ResponseEntity.ok(response);
    }

    @PostMapping("/refresh")
    @Operation(summary = "刷新访问令牌", description = "使用刷新令牌换取新的访问令牌")
    public ResponseEntity<TokenResponse> refresh(@Valid @RequestBody RefreshRequest request) {
        if (!tokenProvider.validateRefreshToken(request.getRefreshToken())) {
            throw new BadCredentialsException("刷新令牌已失效");
        }
        String tenantId = tokenProvider.extractTenantId(request.getRefreshToken());
        String username = tokenProvider.extractUsername(request.getRefreshToken());
        if (tenantId == null || username == null) {
            throw new BadCredentialsException("刷新令牌信息不完整");
        }
        UserDetails userDetails = authenticationService.loadUser(tenantId, username);
        TokenResponse response = buildTokenResponse(tenantId, userDetails);
        log.info("租户 [{}] 用户 [{}] 刷新令牌成功", tenantId, username);
        return ResponseEntity.ok(response);
    }

    private TokenResponse buildTokenResponse(String tenantId, UserDetails userDetails) {
        String accessToken = tokenProvider.generateAccessToken(tenantId, userDetails);
        String refreshToken = tokenProvider.generateRefreshToken(tenantId, userDetails);
        long expiresIn = securityProperties.getJwt().getExpirationSeconds();
        long refreshExpiresIn = securityProperties.getJwt().getRefreshExpirationSeconds();
        return new TokenResponse(accessToken, refreshToken, expiresIn, refreshExpiresIn, tenantId, userDetails.getUsername());
    }

    public static class LoginRequest {

        @NotBlank(message = "租户ID不能为空")
        private String tenantId;

        @NotBlank(message = "用户名不能为空")
        private String username;

        @NotBlank(message = "密码不能为空")
        private String password;

        public String getTenantId() {
            return tenantId;
        }

        public void setTenantId(String tenantId) {
            this.tenantId = tenantId;
        }

        public String getUsername() {
            return username;
        }

        public void setUsername(String username) {
            this.username = username;
        }

        public String getPassword() {
            return password;
        }

        public void setPassword(String password) {
            this.password = password;
        }
    }

    public static class RefreshRequest {

        @NotBlank(message = "刷新令牌不能为空")
        private String refreshToken;

        public String getRefreshToken() {
            return refreshToken;
        }

        public void setRefreshToken(String refreshToken) {
            this.refreshToken = refreshToken;
        }
    }

    public static class TokenResponse {

        private final String accessToken;
        private final String refreshToken;
        private final long expiresIn;
        private final long refreshExpiresIn;
        private final String tenantId;
        private final String username;

        public TokenResponse(String accessToken,
                             String refreshToken,
                             long expiresIn,
                             long refreshExpiresIn,
                             String tenantId,
                             String username) {
            this.accessToken = accessToken;
            this.refreshToken = refreshToken;
            this.expiresIn = expiresIn;
            this.refreshExpiresIn = refreshExpiresIn;
            this.tenantId = tenantId;
            this.username = username;
        }

        public String getAccessToken() {
            return accessToken;
        }

        public String getRefreshToken() {
            return refreshToken;
        }

        public long getExpiresIn() {
            return expiresIn;
        }

        public long getRefreshExpiresIn() {
            return refreshExpiresIn;
        }

        public String getTenantId() {
            return tenantId;
        }

        public String getUsername() {
            return username;
        }
    }
}
